/**
 *  \file I3OCDStateInfo.h
 *  \brief Defines the fields of the I3 specific OCD state information of a
 *  a connection.
*/
#ifndef I3_LAYER_STATE_INFO
#define I3_LAYER_STATE_INFO 1

#include "OCD_include.h"

extern "C" {
    #include "i3.h"
    #include "i3_client_api.h"
}

/**
  * This denotes an i3 virtual node created 
  * in response to a DNS request for a remote host.
  */
#define I3_VN_TYPE_LOCAL_CREATED 100

/**
  * This denotes an i3 virtual node created in reponse to
  * a private trigger request from a remote host.
  */
#define I3_VN_TYPE_REMOTE_CREATED 200


// State variables for I3OCDStateInfo->state
// These are I3 specific
#define FAKE_STATE_NEW     0x00
#define FAKE_STATE_CNF     0x01
#define FAKE_STATE_OK      0x02
#define FAKE_STATE_PARTNER_DORMANT 0x03
#define FAKE_STATE_RENEW 0x04
#define FAKE_STATE_RECNF 0x05

/** Indicates a new connection like FAKE_STATE_NEW, but connection is through a server proxy. */
#define FAKE_STATE_NEW_VIA_SERVER_PROXY 0x06

#define FAKE_STATE_PRIV_TRIG_INSERTED 0x07
#define FAKE_STATE_PRIV_TRIG_REQUESTED 0x08

class I3Id;
class I3OverlayNetwork;
class I3Trigger;
class I3TimerEvent;

class I3OCDStateInfo:public OCDStateInfo {
    
public:

    /** The state of this i3 Virtual Node - FAKE_OK etc. */
    char              state;
    
    /** The private id of this virtual node */
    ID prv_id;
    
    /** The key of the private trigger associated with this virtual node */
    Key               prv_trig_key;

    /** The private i3 trigger associated with this virtual node. */
    cl_trigger        *prv_cl_trig;

    /**
      * The remaining of the stack of ids on which the private trigger request of this
      * I3 OCD state was received.
      */
    ID triggerStack[I3_MAX_STACK_LEN];

    /** The number of IDs in the triggerStack */
    int triggerStackLen;
    
    /** The private i3 trigger associated with this virtual node.
      * This is the private trigger which was inserted on this local machine.
      * TODO avoid redundant prv_trig.
      */
    I3Trigger*      localPrivateTrigger;

    /** If this I3OCD State was created on receiving a private trigger request, 
      * then this field contains the ID on which the private trigger request
      * was received.
      */
    ID contactId;
    
    /** The I3 overlay associated with this state */
    I3OverlayNetwork *overlay;
    
    /** What type of addresses to use - IPv4 or IPv6? */
    int addr_type;

    /** The local i3 address of this i3 virtual node,
     * i.e. the i3 address of the proxy in which this node resides.
     */
    i3_addr           localI3Address;

    /** This timer is used for re-requesting a private trigger confirmation
     * from the remote end point of the virtual node.
     */
    I3TimerEvent *prvTriggerConfirmationTimer;
    
    /**
      * When was this I3 VN created? - I3_VN_TYPE_LOCAL_CREATED or I3_VN_TYPE_REMOTE_CREATED
      */
    int i3VNType;
    
    // fakeIP defined in parent class VirtualNode
    
    /** The private i3 id of the remote server being masqueraded. */
    I3Id* remotePrivateId;
    
    /** This is the stack of i3 Ids corresponding to the private trigger of the remote
      * end point this VN is masquerading.  The stack contains the id in the field remoteId.
      * We need this duplicate i3_stack field because it is needed in cl_sendto_stack.
      */
    i3_stack          remotePrivateIdStack; //erstwhile dest_stack

    /**
      * The public i3 id of the remote server being masqueraded.
      */
    I3Id* remotePublicId;
    /**
      * This is the stack of ids corresponding to the public trigger of the remote end point.
      */
    i3_stack    remotePublicIdStack;    //erstwhile dns_stack
    
    //START - data struct copied from fake_dns_req
    unsigned long           num_req;
    int                     answered;

    /** Number of times a private id was requested from a remote host. */
    int     numRemotePrivateIdRequests;
    
    char              retry;
   
    /**
      * If this flag is true, the connection for this VN will be set to READY
      * even before the private trigger confirmation is received from the 
      * remote end point.
      */
    bool enableFastConnectionSetup;
    
    /** Has the local private trigger for this VN already inserted? */
    bool localPrivTrigInsertedFlag;
    
    /** This flag is used to indicate that this i3 virtual node is being
     * processed during crash recover.  So some of the steps undergone
     * by this virtual node to establish a new connection will be different
     * from that during normal operations.
     */
    bool crashRecoveryInProgress;

    /**
      * This flag indicates if the i3 id of the remote end point associated with this VN was obtained by hashing the name.
      * (i.e. not from the address book)
      */
    bool nameHashedFlag;
   
    I3OCDStateInfo(LayerHandle myHandle, OCI* oci, I3OverlayNetwork *overlay);
    static I3OCDStateInfo* constructState (char *journalRecordStr, OCI *oci, I3OverlayNetwork *overlay);
   
    void getJournalRecord(char * buf);

    void connectionFailed();

    ~I3OCDStateInfo();

    friend class I3OverlayNetwork;
};

#endif
